//Copyright (c) 2010 Jimmy Merari

//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:

//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.

var Scriptagility = {};
var S = Scriptagility;

S.PnlEditArea = C.ActiveAgent.extend(
{
    init:function()
    {
        this._super();
    
    },
    fini:function()
    {
        var editorDoc = $j('frame_txtEditor')[0].contentDocument;
        $j(editorDoc).unbind('keydown');
    },
    setup:function()
    {
        $j(window).bind('resize',this.onResize);
        //setTimeout(resizeHelper, 2000);

        this.setupEditAreaCallback();
        this.setupEditArea();
    
    },
    setupEditArea : function()
    {
        var $this = this;
        setTimeout(function()
        {
            var editorDoc = $j('#frame_txtScript')[0].contentDocument;
            $j(editorDoc).bind('keydown',{sender:$this}, $this.onKeydown);
        },2000);

        editAreaLoader.init(
        {
            id : 'txtScript',
            syntax: 'js',
            start_highlight: false,
            display: 'onload',
            replace_tab_by_spaces: 4,
            toolbar:'save,|,search, go_to_line,|, change_smooth_selection, highlight, reset_highlight, syntax_selection,|, help',
            allow_resize: 'no',
            allow_toggle: false,
            word_wrap:false,
            is_multi_files:true,
            save_callback: 'S.onSaveClick',
            EA_load_callback:'S.onResize',
            //EA_file_switch_on_callback:'S.view.onTabVisible',
            //EA_file_switch_off_callback:'S.view.onTabInvisible',
            EA_file_close_callback:'S.onFileClosing'
        });
        
        
    },
    setupEditAreaCallback:function()
    {
        var $this = this;
        function saveHelper(editorId)
        {
            $this.onSaveClick(editorId);
        }
        
        //global, needed for EditArea callback
        S.onResize = this.onResize; 
        S.onSaveClick = saveHelper;
        S.onFileClosing = this.onFileClosing;
        S.bDeleting = false;
    },
    onResize : function()
    {
        $j('#pnlMain').width(Geometry.getViewportWidth()).height(Geometry.getViewportHeight());
        var w = $j('#pnlEditor').width();
        var h = $j('#pnlEditor').height();
        $j('#frame_txtScript').width(w);
        $j('#frame_txtScript').height(h);
        
        var l = $j('#pnlEditor').attr('offsetLeft');
        $j('#pnlFeedback').css('left',(l+5).toString()+'px');
    },

    onEditAreaLoad : function(id)
    {
        var w = $j('#pnlEditor').width();
        var h = $j('#pnlEditor').height();
        $j('#frame_txtScript').width(w);
        $j('#frame_txtScript').height(h);
    },

    onTabInvisible : function(fileInfo)
    {
    },

    onFileClosing : function(fileInfo)
    {
        if(!S.bDeleting)
        {
            var toReturn = true;
            if(fileInfo.edited)
            {
                toReturn = confirm('File is not saved. Discard changes?');
            }
            return toReturn;
        }
        else
            return true;
    },
    onSaveClick : function(editorId)
    {
        var fileInfo = editAreaLoader.getCurrentFile(editorId);
        if(fileInfo.id != '')
        {
            var arg = 
            {
                scriptId:fileInfo.id,
                script:fileInfo.text
            }
            this.trigger('evView_SaveScript',arg);
        }
    },
    openScript : function(scriptObj)
    {
        var fileInfo =
        {
            "id":scriptObj.scriptId,
            "title":scriptObj.scriptName,
            "text":scriptObj.script
        };
        editAreaLoader.openFile('txtScript', fileInfo);
    },
    closeScript : function(scriptId)
    {
        S.bDeleting = true;
        editAreaLoader.closeFile('txtScript', scriptId);
        S.bDeleting = false;
    },
    confirmSaved:function(scriptId)
    {
        editAreaLoader.setFileEditedMode('txtScript', scriptId.toString(), false);    
    },
    getDirtyFile:function()
    {
        var allFile = editAreaLoader.getAllFiles('txtScript');
        var dirty = [];
        for(var key in allFile)
        {
            if(allFile[key].edited)
                dirty.push(allFile[key].title);
        }
        return dirty;
    },
    onKeydown:function(ev)
    {
        if(ev.keyCode == 83 && ev.ctrlKey)
        {
            ev.preventDefault();
            var $this = ev.data.sender;
            $this.onSaveClick('txtScript');
        }
    }

    
});

S.PnlScriptList = C.ActiveAgent.extend(
{
    init:function()
    {
        this._super();
    },
    fini:function()
    {
    
    },
    setup: function()
    {
        $j('#cmdAdd').bind('click',{sender:this},this.onAddClick);
        $j('#scriptContainer').bind('click',{sender:this},this.onScriptContainerClick);
        
        this.compileTemplate();
        this.setupDlgAbout();

    },
    setupDlgAbout:function()
    {
        $j('#dlgAbout').jqm({modal:true,zIndex:5001});
        $j('#dlgAbout').jqDrag('.jqDrag');
        $j('#cmdAbout').click(function()
        {
            $j('#dlgAbout').jqmShow();
        });
        
        $j('#btnCloseAbout').click(function()
        {
            $j('#dlgAbout').jqmHide();
        });
    },
    onAddClick:function(ev)
    {
        var $this = ev.data.sender;
        $this.trigger('evView_ReqAddScript',{});
    },
    compileTemplate:function()
    {
        var classMap = ['ui-silk-bullet-red','ui-silk-bullet-arrow-top','ui-silk-bullet-arrow-up','ui-silk-bullet-go','ui-silk-bullet-arrow-down','ui-silk-attach']; 
        var titleMap = ['Disabled','Head','Upper','InPlace','Lower','External']; 
    
        var directive =
        {
            'li.script-item':{
                'script<-result':
                {
                    '@id':'script.scriptId',
                    '@idx':function(arg){return arg.pos;},
                    '@title': function(arg){ return 'Order:'+arg.item.scriptOrder+', '+titleMap[arg.item.placementInt];},
                    'span.icon@class+':function(arg){ return classMap[arg.item.placementInt]; },
                    'span.script-name':'script.scriptName'
                }
            }
        };
        
        this.scriptRenderer = $p($j($j('#tmplScriptList').html())[0]).compile(directive);
    
    },

    renderScriptList : function(scriptList)
    {
        var data = {result:scriptList};
        $j('#scriptContainer').html(this.scriptRenderer(data));
    },
    onScriptContainerClick:function(ev)
    {
        var $this = ev.data.sender;
        var $target = $j(ev.target);
        if($target.hasClass('triggerProp'))
        {
            var idx = $target.parents().filter('.script-item').attr('idx');
            $this.trigger('evView_ReqEditScript', {idx:idx});
        }
        else if($target.hasClass('triggerDelete'))
        {
            var $li = $target.parents().filter('.script-item');
            var idx = $li.attr('idx');
            $this.trigger('evView_ReqDeleteScript', {idx:idx});
        }
        else if($target.hasClass('script-name'))
        {
            var $li = $target.parents().filter('.script-item');
            var idx = $li.attr('idx');
            $this.trigger('evView_ReqOpenScript', {idx:idx});
        }
        else if($target.hasClass('script-item'))
        {
            var idx = $target.attr('idx');
            $this.trigger('evView_ReqOpenScript', {idx:idx});
        }
        return false;
    }
});

S.DlgProperties = C.ActiveAgent.extend(
{
    init:function()
    {
        this._super();
    
    },
    fini:function()
    {
    
    },
    setup:function()
    {
        $j.metadata.setType('attr','validate');
        $j('#dlgScriptProperties').jqm({modal:true,zIndex:5001});
        $j('#dlgScriptProperties').jqDrag('.jqDrag');

        $j('#dlgScriptProperties').validate(
        {
            onsubmit:false
        });

        $j('#cmdCancel').bind('click',{sender:this}, this.onCancelClick);
        $j('#btnSave').bind('click',{sender:this}, this.onSaveClick);
    },
    onSaveClick:function(ev)
    {
        var $this = ev.data.sender;
        //hydrate here...
        if($j('#dlgScriptProperties').valid())
        {
            var formHash = $j('#dlgScriptProperties').formHash();
            formHash.moduleId = ModuleId;
            if(formHash.index == '')
            {
                formHash.index = -1;
                formHash.script = '';
                $this.trigger('evView_CommitAddScript',{script:formHash});
            }
            else
            {
                $this.trigger('evView_CommitSaveScript',{script:formHash});
            }
        }
    },
    onCancelClick:function(ev)
    {
        var $this = ev.data.sender;
        $j('#dlgScriptProperties').jqmHide();
    },
    openNew:function()
    {
        C.clearField('#dlgScriptProperties');
        $j('#dlgScriptProperties').jqmShow();
    },
    openEdit : function(scriptObj)
    {
        C.clearField('#dlgScriptProperties');
        $j('#dlgScriptProperties').formHash(scriptObj);
        $j('#dlgScriptProperties').jqmShow();
    },
    close:function()
    {
        $j('#dlgScriptProperties').jqmHide();
    }
    
});

S.Controller = C.ActiveAgent.extend(
{
    init:function()
    {
        this._super();
        var channel = C.ajaxQueue;
        this.proxy = new ScriptagilityApi();
        this.proxy.channel = channel;

        this.scriptCache = [];
        this.scriptIndex = {};
    
        this.pnlEditArea = new S.PnlEditArea();
        this.pnlScriptList = new S.PnlScriptList();
        this.dlgProperties = new S.DlgProperties();
    },
    fini:function()
    {
    
    },
    setup:function()
    {
        this.pnlEditArea.setup();
        this.pnlScriptList.setup();
        this.dlgProperties.setup();
        
        var $this = this;
        function unloadHelper(ev)
        {
            return $this.onUnload(ev);
        }
        window.onbeforeunload = unloadHelper;
        
        this.mapEventAction(this.pnlScriptList, 'evView_ReqOpenScript', this.onReqOpenScript);
        this.mapEventAction(this.pnlScriptList, 'evView_ReqAddScript', this.onReqAddScript);
        this.mapEventAction(this.pnlScriptList, 'evView_ReqEditScript', this.onReqEditScript);
        this.mapEventAction(this.pnlScriptList, 'evView_ReqDeleteScript', this.onReqDeleteScript);

        this.mapEventAction(this.pnlEditArea, 'evView_SaveScript', this.onSaveScript);
        
        this.mapEventAction(this.dlgProperties, 'evView_CommitSaveScript', this.onCommitSaveScript);
        this.mapEventAction(this.dlgProperties, 'evView_CommitAddScript', this.onCommitAddScript);

        this.downloadScripts(ModuleId); //var ModuleId hydrated from server
    
    },
    onReqOpenScript:function(arg)
    {
        //nantinya ini musti request lagi ke server!!
        var scriptObj = this.scriptCache[arg.idx];    
        this.pnlEditArea.openScript(scriptObj);
    },
    onReqAddScript:function(arg)
    {
        this.dlgProperties.openNew();
    },
    onReqEditScript:function(arg)
    {
        var scriptObj = this.scriptCache[arg.idx];
        scriptObj.index = this.scriptIndex[scriptObj.scriptId];
        this.dlgProperties.openEdit(scriptObj);
    },
    onReqDeleteScript:function(arg)
    {
        var $this = this;
        var scriptObj = this.scriptCache[arg.idx];    
        if(confirm('Delete "' + scriptObj.scriptName + '" ?\n\nTHIS ACTION CANNOT BE UNDONE !'))
        {
            this.pnlEditArea.closeScript(scriptObj.scriptId);
            this.showThrobber('Deleting...');
            this.proxy.deleteScript(scriptObj.scriptId, function(response)
            {
                if(!response.error)
                {
                    $this.hideThrobber('Deleted');
                    $this.downloadScripts(ModuleId);
                }
                else
                {
                    alert(response.error.message);
                    $this.hideThrobber('Error');
                }
            });
        }
    },
    
    updateCache:function(scriptList)
    {
        this.scriptCache = scriptList;
        this.scriptIndex = {};
        for(var i = 0, ii = scriptList.length; i < ii; i++)
        {
            this.scriptIndex[scriptList[i].scriptId] = i;
        }
    },
    downloadScripts : function(moduleId)
    {
        var $this = this;
        this.proxy.getScript(moduleId, function(response)
        {
            if(!response.error)
            {
                $this.updateCache(response.result);
                $this.pnlScriptList.renderScriptList(response.result);
            }
            else alert(response.error.message);
        });
    },
    onSaveScript : function(arg)
    {
        var $this = this;
        var scriptInfo = this.scriptCache[this.scriptIndex[arg.scriptId]];
        var toSave = $j.extend({},scriptInfo);
        toSave.script = arg.script;
        $this.showThrobber('Saving...');
        this.proxy.saveScript(toSave, function(response)
        {
            if(!response.error)
            {
                scriptInfo.script = toSave.script;
                $this.pnlEditArea.confirmSaved(arg.scriptId);
                $this.hideThrobber('Saved');
            }
            else 
            {
                $this.hideThrobber('Error');
                alert(response.error.message);
            }
        });
    },
    onCommitAddScript : function(arg)
    {
        var $this = this;
        this.showThrobber('Saving...');
        this.proxy.addScript(arg.script, function(response)
        {
            if(!response.error)
            {
                //di sini musti update scriptList dengan script yg baru
                arg.script.scriptId = response.result;
                $this.scriptCache.push(arg.script);
                $this.scriptIndex[arg.script.scriptId] = $this.scriptCache.length-1;
                $this.hideThrobber('Saved');
                $this.downloadScripts(ModuleId);
            }
            else 
            {
                $this.hideThrobber('Error');
                alert(response.error.message);
            }
            $this.dlgProperties.close();
        });
    },    
    onCommitSaveScript:function(arg)
    {
        var $this = this;
        var obj = arg.script;
        var scriptInfo = this.scriptCache[obj.index];
        var toSave = $j.extend({},scriptInfo, obj);
    
        this.showThrobber('Saving...');
        this.proxy.saveScript(toSave, function(response)
        {
            if(!response.error)
            {
                scriptInfo = toSave;
                //di sini musti update scriptList dengan script yg baru
                $this.dlgProperties.close();
                $this.hideThrobber('Saved');
                $this.downloadScripts(ModuleId);
            }
            else 
            {
                alert(response.error.message);
                $this.dlgProperties.close();
                $this.hideThrobber('Error');
            }
        });
    },
    showThrobber:function(txt)
    {
        $j('#pnlFeedback').text(txt).show();
    },
    hideThrobber:function(txt)
    {
        $j('#pnlFeedback').text(txt);
        setTimeout(function()
        {
            $j('#pnlFeedback').slideToggle('slow');
        },1000);
    },
    onUnload:function(ev)
    {
        var $this = this; //ev.data.sender;
        var dirtyFile = $this.pnlEditArea.getDirtyFile();
        if(dirtyFile.length)
        {
            var msg = 'The following script has modified:\n';
            for(var i = 0; i < dirtyFile.length; i++)
            {
                msg += ' - ' + dirtyFile[i] + '\n';
            }
            if(ev) ev.returnValue = msg;
            return msg;
        }
    },
    onKeydown:function(ev)
    {
        console.log(ev);
    }
});

$j(document).ready(function()
{
    S.ctrl = new S.Controller();
    S.ctrl.setup();
});
